package com.imchenio.utils.redis;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
@EnableScheduling
public class MachineIdGenerateUtil {
    private static int machineId = -1;

    private static final String MACHINE_ID_REDIS_KEY_PREFIX = "distribution_machine_id:";

    private final RedisTemplate<String, Object> redisTemplate;


    public MachineIdGenerateUtil(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    //----------------------------------------------------------------
    // 机器id注册，销毁和续期
    //----------------------------------------------------------------

    @PostConstruct
    public void generateMachineId() throws UnknownHostException {
        // 获取ip并将ip转化为数字
        String ip = InetAddress.getLocalHost().getHostAddress();
        int ipNum = Integer.parseInt(ip.replace(".", ""));

        int originalMachineId = ipNum % 32;
        int machineId = originalMachineId;
        while (true) {
            String redisKey = MACHINE_ID_REDIS_KEY_PREFIX + machineId;
            boolean isGet = Boolean.TRUE.equals(
                    redisTemplate.opsForValue().setIfAbsent(redisKey, "nonsense", 30, TimeUnit.MINUTES)
            );
            if (isGet) {
                MachineIdGenerateUtil.machineId = machineId;
                log.info("成功注册机器id,redisKey={}", redisKey);
                break;
            }

            if (originalMachineId < 16) {
                machineId--;
            } else {
                machineId++;
            }

            if (machineId >= 32 || machineId < 0) {
                log.error("机器id注册失败,originalId={},machineId={}", originalMachineId, machineId);
                return;
            }
        }

    }

    @PreDestroy
    public void destroyMachineId() {
        String redisKey = MACHINE_ID_REDIS_KEY_PREFIX + machineId;
        redisTemplate.delete(redisKey);
        log.info("成功销毁机器id,redisKey={}", redisKey);
    }

    @Scheduled(cron = "0 0/1 * * * ?")
    public void refreshExpireTime() {
        log.info("当前工作id={}", machineId);
        if (machineId == -1) {
            return;
        }
        String redisKey = MACHINE_ID_REDIS_KEY_PREFIX + machineId;
        redisTemplate.expire(redisKey, 60, TimeUnit.MINUTES);
    }

    //----------------------------------------------------------------
    // 对外提供的方法
    //----------------------------------------------------------------

    public static int getMachineId() {
        return machineId;
    }
}
